package it.orma.iridehr.repository.ricercaAziende;

import it.orma.iridehr.controllers.form.ricercaAziende.RicercaAziendeForm;
import it.orma.iridehr.controllers.ricerca.RicercaForm;
import it.orma.iridehr.entities.*;
import it.orma.iridehr.entities.azienda.Azienda;
import it.orma.iridehr.entities.azienda.ContattoAzienda;
import it.orma.iridehr.services.helper.RisultatoRicerca;

import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class RicercaAziendeRepository {

	@PersistenceContext
	private EntityManager entityManager;

	public List<RisultatoRicerca> ricercaAziende(RicercaForm ricercaForm){
		ricercaForm.setTipoRicerca("cercacandidati");
		
		StringTokenizer tokenizerNome = new StringTokenizer(ricercaForm.getNome().toUpperCase().replaceAll(" +"," "));
		StringTokenizer tokenizerCognome = new StringTokenizer(ricercaForm.getCognome().toUpperCase().replaceAll(" +"," "));
		String criteria = ricercaForm.getCriteria();
		StringBuilder whereClauseCognome = new StringBuilder("(");
		StringBuilder whereClauseNome = new StringBuilder("(");
		while (tokenizerCognome.hasMoreTokens()){
			String token = tokenizerCognome.nextToken();
			whereClauseCognome.append(" upper(d.cognome) like '%"+token.toUpperCase()+"%' "+ criteria);
		}
		while (tokenizerNome.hasMoreTokens()){
			String token = tokenizerNome.nextToken();
			whereClauseNome.append(" upper(d.nome) like '%"+token.toUpperCase()+"%' "+ criteria);
		}
		
		String queryHql = "select count(d) "
		+ " from "+ DatiGenerali.class.getCanonicalName() + " as d inner join d.schedaCandidato s "
		+" where 1=1 ";
		if (whereClauseCognome.length()>1)
			queryHql+=" and "+whereClauseCognome.toString().substring(0,whereClauseCognome.toString().lastIndexOf(criteria)).concat(")");
		if (whereClauseNome.length()>1)
			queryHql+=" and "+whereClauseNome.toString().substring(0,whereClauseNome.toString().lastIndexOf(criteria)).concat(")");
//		+ " where upper(d.cognome) like '%"+ricercaForm.getQuery().toUpperCase() + "%' or "
//		+ " upper(d.nome) like '%"+ricercaForm.getQuery().toUpperCase() + "%'";
		Query query = entityManager.createQuery(queryHql);
		ricercaForm.setResultSize(new Long((Long) query.getSingleResult()).intValue());
		
		queryHql = "select s.idSchedaCandidato,s.idDocumentoCurriculum, d.cognome, d.nome, d.dataDiNascita, d.comuneDiNascita, d.provinciaDiNascita, s.dataModifica "
				+ " from "+ DatiGenerali.class.getCanonicalName() + " as d inner join d.schedaCandidato s "
//				+ " where upper(d.cognome) like :query or "
//				+ " upper(d.nome) like :query";
				+" where 1=1 ";
				if (whereClauseCognome.length()>1)
					queryHql+=" and "+whereClauseCognome.toString().substring(0,whereClauseCognome.toString().lastIndexOf(criteria)).concat(")");
				if (whereClauseNome.length()>1)
					queryHql+=" and "+whereClauseNome.toString().substring(0,whereClauseNome.toString().lastIndexOf(criteria)).concat(")");
//		session. .setMaxResults(ricercaForm.getRecordPerPagina());
//		getHibernateTemplate().setFetchSize(ricercaForm.getPagina());
		query = entityManager.createQuery(queryHql);
//		query.setParameter("query", "%"+ricercaForm.getQuery().toUpperCase()+"%");

		query.setFirstResult(ricercaForm.getPagina());
		query.setMaxResults(ricercaForm.getRecordPerPagina());
		List risultati = query.getResultList();

		return convertiLista(risultati);
	}
	
	public List<Azienda> ricercaAzienda(String nomeAzienda){
		String queryHql = "select s "+
				 " from "+Azienda.class.getCanonicalName()+" s"+
		         " where s.nome like ? order by s.nome";
		Query query = entityManager.createQuery(queryHql).setParameter(1, "%"+nomeAzienda+"%");

		List risultati = query.getResultList();
		entityManager.detach(risultati);
		
		return risultati;
	}
	
	public Azienda ricercaAziendaById(Integer idAzienda){
		String queryHql = "select s "+
				 " from "+Azienda.class.getCanonicalName()+" s"+
		         " where s.idAzienda = ? ";
		Query query = entityManager.createQuery(queryHql).setParameter(1, idAzienda);

		Azienda risultato = (Azienda) query.getSingleResult();
		entityManager.detach(risultato);
		
		return risultato;
	}
	
	public List<Azienda> ricercaAzienda(Azienda azienda){
		
		String queryHql = "select s "+
				 " from "+Azienda.class.getCanonicalName()+" s"+
		         " where UPPER(s.nome) = ?"+
				 " and UPPER(s.indirizzoVia) = ?"+
				 " and UPPER(s.indirizzoCitta) = ?"+
				 " and UPPER(s.indirizzoProvincia) = ?"+
				 " and UPPER(s.indirizzoCAP) = ?"+
				 " and UPPER(s.indirizzoNazione) = ?";
		
		Query query = entityManager.createQuery(queryHql);
		query.setParameter(1, azienda.getNome().toUpperCase());
		query.setParameter(2, azienda.getIndirizzoVia().toUpperCase());
		query.setParameter(3, azienda.getIndirizzoCitta().toUpperCase());
		query.setParameter(4, azienda.getIndirizzoProvincia().toUpperCase());
		query.setParameter(5, azienda.getIndirizzoCAP().toUpperCase());
		query.setParameter(6, azienda.getIndirizzoNazione().toUpperCase());

		List risultati = query.getResultList();
		entityManager.detach(risultati);
		
		return risultati;
	}

	private List<RisultatoRicerca> convertiLista(List risultati) {
		List<RisultatoRicerca> risultatiRicerca = new ArrayList<RisultatoRicerca>();
		for (Iterator iterator = risultati.iterator(); iterator
				.hasNext();) {
			Object[] record = (Object[]) iterator.next();
			StringBuilder dettaglio = new StringBuilder((String) record[3]).append(" ").append(record[2]);
			dettaglio.append(" nato/a il ").append(DateFormatUtils.format((Date)record[4],"dd/MM/yyyy")).append(" a ").append(record[5]).append(" (").append(record[6])
			.append(")");
			RisultatoRicerca rr = new RisultatoRicerca((Long)record[0], (String)record[1], dettaglio.toString(), (Date)record[7]);
			risultatiRicerca.add(rr);
		}
		return risultatiRicerca;
	}

	public Azienda caricaAzienda(Integer idAzienda){
		String hql = "select s from "+Azienda.class.getName()+" as s where s.idAzienda = ?";
		Azienda azienda = (Azienda) entityManager.createQuery(hql).setParameter(1, idAzienda).getSingleResult();
		entityManager.detach(azienda);
		return azienda;
	}
	
	public Azienda creaAzienda(){
		Azienda azienda = new Azienda();
		azienda.setDataCreazione(new Date());

		return azienda;
	}
	
	public List<ContattoAzienda> caricaContatti(Integer idAzienda){
		String hql = "select s from "+ContattoAzienda.class.getName()+" as s where s.idAzienda = ? order by tipo asc";
		List<ContattoAzienda> ca = (List<ContattoAzienda>) entityManager.createQuery(hql).setParameter(1, idAzienda).getResultList();
		entityManager.detach(ca);
		return ca;
	}
	
	public ContattoAzienda caricaContatto(Long idContatto){
		String hql = "select s from "+ContattoAzienda.class.getName()+" as s where s.idContatto = ?";
		ContattoAzienda ca = (ContattoAzienda) entityManager.createQuery(hql).setParameter(1, idContatto).getSingleResult();
		entityManager.detach(ca);
		return ca;
	}

	public StudiCompiuti caricaStudiCompiuti(SchedaCandidato schedaCandidato) {
		String hql ="select s from "+StudiCompiuti.class.getName()+" as s left join fetch s.titoliDiStudio as t inner join fetch s.schedaCandidato sc where s.schedaCandidato=?";
		StudiCompiuti sc = new StudiCompiuti();
		try{
			sc = (StudiCompiuti) entityManager.createQuery(hql).setParameter(1, schedaCandidato).getSingleResult();
		}catch (NoResultException ne){
			sc.setTitoliDiStudio(new HashSet<TitoloDiStudio>());
			sc.setSchedaCandidato(schedaCandidato);
			sc.setDataCreazione(new Date());
			entityManager.persist(sc);
		}
		return sc;
	}

	public TitoloDiStudio caricaTitoloDiStudio(Long idTitoloDiStudio){
		String hql = "select t from "+TitoloDiStudio.class.getName()+" as t inner join t.studiCompiuti as s where t.idTitoloDiStudio =?";
		TitoloDiStudio ts = (TitoloDiStudio) entityManager.createQuery(hql).setParameter(1, idTitoloDiStudio).getSingleResult();
		return ts;
	}

	public LingueConosciute caricaLingueConosciute(SchedaCandidato schedaCandidato) {
		String hql ="select l from "+LingueConosciute.class.getName()+" as l left join fetch l.altreLingue as a inner join fetch l.schedaCandidato sc where l.schedaCandidato=?";
		LingueConosciute lc = new LingueConosciute();
		try{
			lc = (LingueConosciute) entityManager.createQuery(hql).setParameter(1, schedaCandidato).getSingleResult();
		}catch(NoResultException ne){
			lc.setSchedaCandidato(schedaCandidato);
			lc.setDataCreazione(new Date());
			entityManager.persist(lc);

		}
		entityManager.detach(lc);
		return lc;
	}

	public AltraLingua caricaAltraLingua(Long idAltraLingua){
		String hql = "select a from "+AltraLingua.class.getName() +" as a where a.idAltraLingua=:idAltraLingua";
		AltraLingua a = (AltraLingua) entityManager.createQuery(hql).setParameter("idAltraLingua", idAltraLingua).getSingleResult();
		return a;
	}

	public ConoscenzeInformatiche caricaConoscenzaInformatica(SchedaCandidato schedaCandidato){
		String hql = "from "+ConoscenzeInformatiche.class.getName()+" as c left join fetch c.altreConoscenzeInformatiche  where c.schedaCandidato=?";
		ConoscenzeInformatiche conoscenzeInformatiche = new ConoscenzeInformatiche();
		try {
			conoscenzeInformatiche = (ConoscenzeInformatiche) entityManager.createQuery(hql).setParameter(1,schedaCandidato).getSingleResult();
		} catch (NoResultException ne){
			conoscenzeInformatiche.setSchedaCandidato(schedaCandidato);
			conoscenzeInformatiche.setDataCreazione(new Date());
			entityManager.persist(conoscenzeInformatiche);
		}

		entityManager.detach(conoscenzeInformatiche);
		return conoscenzeInformatiche;
	}

	public AltraConoscenzaInformatica caricaAltraConoscenzaInformatica(Long idAltraConoscenzaInformatica){
		AltraConoscenzaInformatica a = entityManager.find(AltraConoscenzaInformatica.class,idAltraConoscenzaInformatica);
		entityManager.detach(a);
		return a;
	}

	public List<EsperienzaLavorativa> caricaEsperienzeLavorative(SchedaCandidato schedaCandidato) {
		String hql = "from "+EsperienzaLavorativa.class.getName()+" as n where n.schedaCandidato=? order by n.dataDa desc";
		List<EsperienzaLavorativa> results = entityManager.createQuery(hql).setParameter(1,schedaCandidato).getResultList();
		entityManager.detach(results);
		return results;
	}

	public EsperienzaLavorativa caricaEsperienzaLavorativa(Long idEsperienzaLavorativa) {
		EsperienzaLavorativa esperienzaLavorativa = entityManager.find(EsperienzaLavorativa.class,idEsperienzaLavorativa);
		entityManager.detach(esperienzaLavorativa);
		return esperienzaLavorativa;
	}
	
	public List<Attitudine> caricaAttitudini(SchedaCandidato schedaCandidato) {
		String hql = "from "+Attitudine.class.getName()+" as n where n.idCandidato=? order by idDomanda asc";
		List<Attitudine> results = entityManager.createQuery(hql).setParameter(1,schedaCandidato.getIdSchedaCandidato()).getResultList();
		entityManager.detach(results);
		return results;
	}
	
	public List<DomandaAttitudinale> caricaDomandeRisposte() {
		String hql = "from "+DomandaAttitudinale.class.getName();
		List<DomandaAttitudinale> results = entityManager.createQuery(hql).getResultList();
		entityManager.detach(results);
		return results;
	}
	
	public AltreInformazioni caricaAltreInfo(SchedaCandidato schedaCandidato) {
		String hql = "select a from "+AltreInformazioni.class.getName() +" as a where a.schedaCandidato=?";
		AltreInformazioni ai = new AltreInformazioni();
		try{	
			 ai =(AltreInformazioni) entityManager.createQuery(hql).setParameter(1,schedaCandidato).getSingleResult();
		}catch(NoResultException ne){
			ai.setSchedaCandidato(schedaCandidato);
			ai.setDataCreazione(new Date());
			entityManager.persist(ai);
		}
		entityManager.detach(ai);
		return ai;
	}

	public void creaDatiGenerali(SchedaCandidato scheda) {
		DatiGenerali dg = new DatiGenerali();
		dg.setSchedaCandidato(scheda);
		dg.setDataCreazione(new Date());
	}
	
	public Integer countAziende(String nome){
		
		String hql = "select count(*) from "+Azienda.class.getCanonicalName()+" as n where n.nome like ?";
		Query query = entityManager.createQuery(hql).setParameter(1, "%"+nome+"%");
		return (new Long((Long) query.getSingleResult()).intValue());
	}
	
	public List<Azienda> caricaAziende(int page,RicercaAziendeForm azForm){
			
			String nativeSql = "SELECT *"+
					  " FROM (SELECT n.sito_web,"+
				      "         n.id_azienda,"+
				      "         n.nome," +
				      " 		n.referente," +
				      "			n.indirizzo_citta," +
				      "			n.indirizzo_via,"+
				      " 		n.settore" +
				      " FROM azienda n"+                 
				      "   WHERE (n.nome like ?) "+
				      "  ORDER BY n.nome ASC) view "+
				      " LIMIT "+(page-1)*10+", 10";
					
			List<Azienda> list = new ArrayList<Azienda>();
			List<Object[]> result = (List<Object[]>) entityManager.createNativeQuery(nativeSql).setParameter(1, "%"+azForm.getQuery()+"%").getResultList();
			Iterator<Object[]> resultIt = result.iterator();
			while(resultIt.hasNext()){
				Object[] record = resultIt.next();
				Azienda azienda = new Azienda();
				azienda.setIdAzienda((Integer)record[1]);
				azienda.setNome((String) record[2]);
				azienda.setSitoWeb((String) record[0]);
				azienda.setReferente((String) record[3]);
				azienda.setIndirizzoCitta((String) record[4]);
				azienda.setIndirizzoVia((String) record[5]);
				azienda.setSettore((String) record[6]);
				list.add(azienda);
			}
			
			entityManager.detach(result);
			entityManager.detach(list);
			
			return list;
		
	}
	
	public List caricaAziende(String nome){
		String hql = "select s from "+Azienda.class.getName()+" as s where UPPER(s.nome) like ? ";
		List<Azienda> aziende = (List<Azienda>) entityManager.createQuery(hql).setParameter(1, "%"+nome+"%").getResultList();
		entityManager.detach(aziende);
		return aziende;
		
	}
	
	
}
